<template>
  <div id="wft-online-edit" ref="onLineEditRef" class="animate__animated">
    <div class="edit-title" :style="editTitleStyle">
      <div>
        <h3>在线编辑器</h3>
        <el-upload class="wft-margin-left-20" action="#" :limit="1" accept=".json, .txt" :show-file-list="false" :before-upload="beforeUpload">
          <el-button :icon="FolderAdd" :style="buttonStyle">导入(json / txt)</el-button>
        </el-upload>
        <el-button @click="updatePanelJson()" class="wft-margin-left-20" :icon="Select" :style="buttonStyle">保存</el-button>
      </div>
      <div>
        <!-- 主题切换 -->
        <div @click="modeChange" class="mode-change">
          <img v-show="mode == 'dark'" src="../static/toolbar/dark.png">
          <img v-show="mode == 'light'" src="../static/toolbar/light.png">
        </div>
        <el-button @click="$emit('close')" circle icon="Close" />
      </div>
    </div>
    <div class="edit-container">
      <MonacoEditor ref="MonacoEditRef" v-model="editJson" language="json" />
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, defineAsyncComponent, computed } from 'vue'
import { FolderAdd, Select } from '@element-plus/icons-vue'
import type { UploadRawFile } from 'element-plus'
import { useMessage, useMessageBox } from '@/hooks'
import { KeyEventEnum } from '@/enums'

const MonacoEditor = defineAsyncComponent(() => import('../components/common/MonacoEditor/index.vue'))

const editJson = ref('')
const onLineEditRef = ref<HTMLDivElement>()
const mode = ref('light')
let pageId = ''

const editTitleStyle = computed(() => {
  const map = <{[k: string]: any}>{
    dark: {
      backgroundColor: '#1e1e1e',
      borderColor: '#2d2d30',
      color: '#BFCBD9'
    },
    light: {
      backgroundColor: '#f0f0f0',
      borderColor: '#f5f5f5',
      color: '#086D6D'
    }
  }
  return {
    backgroundColor: map[mode.value].backgroundColor,
    borderColor: map[mode.value].borderColor,
    color: map[mode.value].color
  }
})

const buttonStyle = computed(() => {
  const map = <{[k: string]: any}>{
    dark: {
      backgroundColor: '#1e1e1e',
      borderColor: '#BFCBD9',
      color: '#BFCBD9'
    },
    light: {
      backgroundColor: '#f0f0f0',
      borderColor: '#086D6D',
      color: '#086D6D'
    }
  }
  return {
    backgroundColor: map[mode.value].backgroundColor,
    borderColor: map[mode.value].borderColor,
    color: map[mode.value].color
  }
})

const emits = defineEmits<{
  (e: 'updatePanelJson', data: TPanel): void
  (e: 'close'): void
}>()

function init(panelJson: TPanel) {
  editJson.value = JSON.stringify(panelJson)
  pageId = panelJson.id
  mode.value = 'light'
  onLineEditRef.value!.classList.add('animate__jackInTheBox')
  onLineEditRef.value!.classList.remove('animate__zoomOut')
  window.addEventListener(KeyEventEnum.ON_KEY_DOWN, onkeyDownHandler)
}

function close() {
  onLineEditRef.value!.classList.add('animate__zoomOut')
  onLineEditRef.value!.classList.remove('animate__jackInTheBox')
  window.removeEventListener(KeyEventEnum.ON_KEY_DOWN, onkeyDownHandler)
}

// 导入json
function beforeUpload(rawFile: UploadRawFile) {
  const { name } = rawFile
  if(name.indexOf('.json') < 0 && name.indexOf('.txt') < 0) {
    return useMessage().error('请选择json文件或txt文件进行导入!')
  }
  const fr = new FileReader()
  fr.readAsText(rawFile)
  fr.onload = () => {
    try {
      const data = JSON.parse(fr.result as string)
      data.id = pageId
      editJson.value = JSON.stringify(data)
      useMessage().success('导入成功')
    } catch(e) {
      useMessage().error('文件解析错误，请确保为json文件且格式数据正确!')
    }
  }
  return false
}

// 更新页面
const updatePanelJson = () => {
  useMessageBox().confirm('是否覆盖源试图内容？此操作不可逆！').then(async () => {
    try {
      const json = JSON.parse(editJson.value) as TPanel
      if(json.id != pageId) {
        return useMessage().error('页面id不一致，请勿修改页面id，请检查！')
      }
      emits('updatePanelJson', json)
      useMessage().success('视图已更新~')
    } catch(e) {
      useMessage().error('数据格式有误！')
    }
  })
}

// 监听 Ctrl + s
function onkeyDownHandler(event: KeyboardEvent) {
  if(event.ctrlKey && event.key == 's') {
    event.preventDefault()
    updatePanelJson()
  }
}

const MonacoEditRef = ref<InstanceType<typeof MonacoEditor>>()

  // 切换主题
const modeChange = () => {
  let theme = ''
  if(mode.value == 'dark') {
    mode.value = 'light'
    theme = 'vs'
  } else {
    mode.value = 'dark'
    theme = 'vs-dark'
  }
  MonacoEditRef.value!.updateOptions({ theme })
}

defineExpose({ init, close })
</script>
<style scoped>
#wft-online-edit {
  width: 100vw;
  height: 100vh;
  position: fixed;
  left: 0;
  top: 0;
  z-index: 999;
}

#wft-online-edit > .edit-title {
  width: 100%;
  height: 60px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  /* background-color: var(--workspace-config-background); */
  background-color: #f0f0f0;
  border-bottom: 1px solid;
  border-bottom-color: #f5f5f5;
  padding: 0 15px;
  box-sizing: border-box;
  transition: all .3s;
}
#wft-online-edit > .edit-title > div {
  height: 100%;
  display: flex;
  align-items: center;
}

#wft-online-edit > .edit-container {
  width: 100%;
  height: calc(100% - 60px);
  background-color: #f5f5f5;
}

#wft-online-edit > .edit-title .mode-change {
  height: 70%;
  padding: 8px 15px;
  box-sizing: border-box;
  border-radius: 4px;
  cursor: pointer;
  transition: all .3s;
  margin-right: 8px;
}
#wft-online-edit > .edit-title .mode-change img {
  height: 100%;
}

#wft-online-edit > .edit-title .tool-dark:hover {
  background-color: rgba(46, 51, 56, .5);
}
#wft-online-edit > .edit-title .tool-light:hover {
  background-color: rgba(46, 51, 56, .09);
}

.wft-margin-left-20 {
  margin-left: 20px;
}
</style>